package com.xyoto.community.service.impl;

import com.github.pagehelper.PageHelper;
import com.xyoto.community.cache.UserCache;
import com.xyoto.community.constant.DatabaseOperationResult;
import com.xyoto.community.constant.OssBucketModuleName;
import com.xyoto.community.constant.UserLoginStatus;
import com.xyoto.community.dto.PageDTO;
import com.xyoto.community.dto.SendPicturePrivateLetterDTO;
import com.xyoto.community.dto.SendTextPrivateLetterDTO;
import com.xyoto.community.dto.UploadPictureDTO;
import com.xyoto.community.entity.main.PrivateLetter;
import com.xyoto.community.entity.main.UserPrivateLetter;
import com.xyoto.community.enums.FileEnum;
import com.xyoto.community.enums.UserEnum;
import com.xyoto.community.enums.WechatLoginEnum;
import com.xyoto.community.exception.ExceptionUtils;
import com.xyoto.community.mapper.main.PrivateLetterMapper;
import com.xyoto.community.mapper.main.UserMapper;
import com.xyoto.community.mapper.main.UserPrivateLetterMapper;
import com.xyoto.community.po.UserPO;
import com.xyoto.community.po.NewPrivateLetterPO;
import com.xyoto.community.service.PictureService;
import com.xyoto.community.service.PrivateLetterService;
import com.xyoto.community.utils.*;
import com.xyoto.community.vo.PrivateLetterVo;
import com.xyoto.community.vo.SendPicturePrivateLetterVO;
import com.xyoto.community.vo.SendTextPrivateLetterVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 私信service实现类
 */
@Slf4j
@Service
public class PrivateLetterServiceImpl implements PrivateLetterService {

    @Autowired
    private PrivateLetterMapper privateLetterMapper;

    @Resource
    private HttpServletRequest httpServletRequest;

    @Autowired
    private PictureService pictureService;

    @Autowired
    private UserPrivateLetterMapper userPrivateLetterMapper;

    @Autowired
    private PrivateLetterService privateLetterService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private UserMapper userMapper;
    @Resource
    private XYOtoOss xyOtoOss;

    /**
     * 发送私信文字
     * @param sendTextPrivateLetterDTO
     * @return
     */
    @Transactional
    @Override
    public Result sendText(SendTextPrivateLetterDTO sendTextPrivateLetterDTO) {
        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);

        Integer friendId = sendTextPrivateLetterDTO.getTargetUserId();

        //校验私信接收者是否存在
        UserCache redisUserMessage = redisUtils.getRedisUserMessage(friendId);
        if (redisUserMessage == null) {
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }

        UserPrivateLetter userPrivateLetter = new UserPrivateLetter();
        userPrivateLetter.setUserId(userId);
        userPrivateLetter.setFriendId(friendId);
        userPrivateLetter.setContent(sendTextPrivateLetterDTO.getContent());
        //创建用户联系
        privateLetterService.userContact(userPrivateLetter);

        // 更新到私信表
        PrivateLetter privateLetter = new PrivateLetter(userId, sendTextPrivateLetterDTO.getTargetUserId());
        privateLetter.setContent(sendTextPrivateLetterDTO.getContent());
        Integer insert = privateLetterMapper.insertOne(privateLetter);
        if (insert < DatabaseOperationResult.SUCCESS){
            log.error("【发送私信文字】,保存到数据库失败，实体参数为：{}",privateLetter);
            ExceptionUtils.error(UserEnum.PRIVATE_LETTER_SAVE_ERROR);
        }
        // 返回数据
        SendTextPrivateLetterVO sendTextPrivateLetterVO = new SendTextPrivateLetterVO();
        sendTextPrivateLetterVO.setContent(privateLetter.getContent());
        sendTextPrivateLetterVO.setSendTime(privateLetter.getCreateTime());
        return Result.success(sendTextPrivateLetterVO);
    }

    /**
     * 发送图片私信内容
     * @param multipartFile 图片
     * @param sendPicturePrivateLetterDTO
     * @return
     */
    @Transactional
    @Override
    public Result sendPicture(MultipartFile multipartFile, SendPicturePrivateLetterDTO sendPicturePrivateLetterDTO) {
        Integer targetUserId = sendPicturePrivateLetterDTO.getTargetUserId();

        //校验私信接收者是否存在
        UserCache redisUserMessage = redisUtils.getRedisUserMessage(targetUserId);
        if (redisUserMessage == null) {
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }

        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        if (userId == UserLoginStatus.UN_LOGIN){
            ExceptionUtils.error(WechatLoginEnum.USER_NOT_LOGIN);
        }

        // 检查图片合法性
        UploadPictureDTO uploadPictureDTO = new UploadPictureDTO();
        uploadPictureDTO.setMultipartFile(multipartFile);
        pictureService.checkPicture(uploadPictureDTO);

        String path = null;

        // 上传图片到oss
        try {
            path = xyOtoOss.uploadFileAvatars(new MultipartFile[]{multipartFile}, OssBucketModuleName.PRIVATE_LETTER);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (path == null){
            ExceptionUtils.error(FileEnum.FILE_UPLOAD_FAIL);
        }

        UserPrivateLetter userPrivateLetter = new UserPrivateLetter();
        userPrivateLetter.setUserId(userId);
        userPrivateLetter.setFriendId(targetUserId);
        userPrivateLetter.setPath(path);
        //创建用户联系
        privateLetterService.userContact(userPrivateLetter);

        // 保存到数据库
        PrivateLetter privateLetter = new PrivateLetter(userId, targetUserId);
        privateLetter.setPath(path);
        Integer insert = privateLetterMapper.insertOne(privateLetter);
        if (insert < DatabaseOperationResult.SUCCESS){
            log.error("【发送私信图片】,保存到数据库失败，实体参数为：{}",privateLetter);
            ExceptionUtils.error(UserEnum.PRIVATE_LETTER_SAVE_ERROR);
        }

        // 返回图片路径和上传时间
        SendPicturePrivateLetterVO sendPicturePrivateLetterVO = new SendPicturePrivateLetterVO(path, privateLetter.getCreateTime());
        return Result.success(sendPicturePrivateLetterVO);
    }

    /**
     * 获取用户私信内容
     * @param targetUserId
     * @param pageDTO
     * @return
     */
    @Override
    public Result getPrivateLetter(Integer targetUserId, PageDTO pageDTO) {

        //分页查询
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());

        //判断目标用户id是否为null或者0
        if (targetUserId == null || targetUserId <= 0){
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }

        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        if (userId == UserLoginStatus.UN_LOGIN){
            ExceptionUtils.error(WechatLoginEnum.USER_NOT_LOGIN);
        }

        List<PrivateLetter> letters = privateLetterMapper.getPrivateLetter(userId,targetUserId);
        if (letters == null || letters.size() <= 0){
            return Result.success(PageUtils.restPage(new ArrayList<>()));
        }

        return Result.success(letters);
    }

    /**
     * 删除私信列表
     * @param privateLetterListId
     * @return
     */
    @Override
    public Result removePrivateLetterList(Integer privateLetterListId) {

        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        if (userId == UserLoginStatus.UN_LOGIN){
            ExceptionUtils.error(WechatLoginEnum.USER_NOT_LOGIN);
        }

        if (privateLetterListId < 0){
            ExceptionUtils.error(UserEnum.PRIVATE_LETTER_LIST_IS_NULL);
        }

        Integer userPrivateLetterId = userPrivateLetterMapper.getUser(privateLetterListId);
        if (!userPrivateLetterId.equals(userId)){
            ExceptionUtils.error(UserEnum.PRIVATE_LETTER_LIST_USER_ERROR);
        }

        Integer removePrivateList = userPrivateLetterMapper.removePrivateList(privateLetterListId);
        if (removePrivateList == null || removePrivateList == 0){
            ExceptionUtils.error(UserEnum.PRIVATE_LETTER_LIST_REMOVE_ERROR);
        }

        return Result.success();
    }

    /**
     * 获取私信列表
     * @return
     */
    @Override
    public List<PrivateLetterVo> getPrivateLetterList() {

        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        if (userId == UserLoginStatus.UN_LOGIN){
            ExceptionUtils.error(WechatLoginEnum.USER_NOT_LOGIN);
        }

        //用于封装最终返回信息
        List<PrivateLetterVo> letterVos = new ArrayList<>();

        //查询用户私信联系人列表
        List<Integer> letterPos = userPrivateLetterMapper.getUserContactList(userId);
        if(letterPos == null || letterPos.size() == 0){
            return letterVos;
        }
        //查询用户私信联系人信息列表
        List<UserPO> userSimpleList = userMapper.getUserSimpleList(letterPos);
        if (userSimpleList == null || userSimpleList.size() == 0){
            log.error("私信联系人信息列表为空,传入实体参数为{}",letterPos);
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }

        //查询用户私信联系人私信内容
        List<NewPrivateLetterPO> letterPos1 = userPrivateLetterMapper.getNewPrivateLetterList(letterPos,userId);
        if (letterPos1 == null || letterPos1.size() == 0){
            log.error("联系人私信内容,传入实体参数为{}",letterPos);
            ExceptionUtils.error(UserEnum.PRIVATE_LETTER_IS_NULL);
        }

        //将用户信息存入map中
        Map<Integer,UserPO> map = userSimpleList.stream().collect(Collectors.toMap(
                UserPO::getId,item-> item
        ));

        //将私信内容放入最终集合中
        for (NewPrivateLetterPO newPrivateLetterPo : letterPos1) {
            Integer targetUserId = newPrivateLetterPo.getFriendId();
            PrivateLetterVo privateLetterVo = new PrivateLetterVo();
            UserPO userPO = map.get(targetUserId);
            privateLetterVo.setPrivateLetterListId(newPrivateLetterPo.getId());
            privateLetterVo.setTargetUserId(targetUserId);
            privateLetterVo.setAvatarUrl(userPO.getAvatarUrl());
            privateLetterVo.setNickName(userPO.getNickname());
            privateLetterVo.setModifiedTime(newPrivateLetterPo.getModifiedTime());
            privateLetterVo.setContent(newPrivateLetterPo.getContent());
            privateLetterVo.setPath(newPrivateLetterPo.getPath());
            privateLetterVo.setCount(privateLetterMapper.getReadCounts(userId,targetUserId),privateLetterVo);

            letterVos.add(privateLetterVo);
        }

        return letterVos;
    }

    /**
     * 保存用户私信联系
     * @param userPrivateLetter
     */
    @Override
    public void saveUserContact(UserPrivateLetter userPrivateLetter){
        userPrivateLetter.setModifiedTime(new Date());
        Integer saveUserContact = userPrivateLetterMapper.saveUserContact(userPrivateLetter);
        if (saveUserContact == null || saveUserContact == 0){
            log.error("保存用户联系失败，实体参数为{}" ,userPrivateLetter);
            ExceptionUtils.error(UserEnum.PRIVATE_LETTER_SAVE_CONTACT_ERROR);
        }
    }

    /**
     * 更新用户私信联系
     * @param userPrivateLetter
     */
    @Override
    public void updateUserContact(UserPrivateLetter userPrivateLetter) {
        Integer updateUserContact = userPrivateLetterMapper.updateUserContact(userPrivateLetter);
        if (updateUserContact == null || updateUserContact == 0){
            log.error("更新用户联系失败，实体参数为{}" ,userPrivateLetter);
            ExceptionUtils.error(UserEnum.PRIVATE_LETTER_UPDATE_CONTACT_ERROR);
        }
    }

    /**
     * 用户联系
     * @param userPrivateLetter
     */
    @Override
    public void userContact(UserPrivateLetter userPrivateLetter){
        Integer userId = userPrivateLetter.getUserId();
        Integer friendId = userPrivateLetter.getFriendId();
        List<Integer> list = userPrivateLetterMapper.getUserContact(userId,friendId);
        //判断用户是否两两联系
        if (list == null || list.size() == 0){
            userPrivateLetter.setUserId(userId);
            userPrivateLetter.setFriendId(friendId);
            privateLetterService.saveUserContact(userPrivateLetter);
            userPrivateLetter.setUserId(friendId);
            userPrivateLetter.setFriendId(userId);
            privateLetterService.saveUserContact(userPrivateLetter);
        }else if(list.size() < 2){
            //判断用户联系中是否为本用户
            if(list.get(0).equals(userId)){
                userPrivateLetter.setUserId(friendId);
                userPrivateLetter.setFriendId(userId);
                privateLetterService.saveUserContact(userPrivateLetter);
                userPrivateLetter.setUserId(userId);
                userPrivateLetter.setFriendId(friendId);
            }else {
                userPrivateLetter.setUserId(userId);
                userPrivateLetter.setFriendId(friendId);
                privateLetterService.saveUserContact(userPrivateLetter);
                userPrivateLetter.setUserId(friendId);
                userPrivateLetter.setFriendId(userId);
            }
            privateLetterService.updateUserContact(userPrivateLetter);
        }else if (list.size() == 2){
            userPrivateLetter.setUserId(userId);
            userPrivateLetter.setFriendId(friendId);
            privateLetterService.updateUserContact(userPrivateLetter);
            userPrivateLetter.setUserId(friendId);
            userPrivateLetter.setFriendId(userId);
            privateLetterService.updateUserContact(userPrivateLetter);
        }else{
            ExceptionUtils.error(UserEnum.PRIVATE_LETTER_SAVE_CONTACT_ERROR);
        }
    }
}
